#include <iostream>
#include <any>
#include <cassert>
#include <typeinfo>
#include <unistd.h>

class Any{
private:
    class holder{
    public:
        virtual ~holder() = default;
        virtual const std::type_info& type() const = 0;
        virtual holder* clone() const = 0;
    };
    template<class T>
    class placeholder: public holder{
    public:
        placeholder(const T& val): _val(val) {} 
        virtual const std::type_info& type() const {return typeid(T);} // 获取子类对象保存的数据类型
        virtual holder* clone() const {return new placeholder(_val);} // 针对当前的对象克隆出一个新的子类对象
    public:
        T _val;    
    };
    holder* _content; // 指向holder的指针

public:
    Any():_content(nullptr) {} 
    template<class T>
    Any(const T& val):_content(new placeholder<T>(val)){} // 模板构造函数
    Any(const Any& other):_content(other._content ? other._content->clone(): nullptr){} // 拷贝构造
    ~Any(){delete _content;}

    Any &swap(Any &other){
        std::swap(_content, other._content); // 交换两个指针
        return *this; // 返回当前对象的引用
    }

    template<class T>
    T *get() const { // 返回子类对象保存数据的指针
        // 保证获取的数据类型和保存的数据类型一致
        // if(typeid(T) != _content->type()) // 如果类型不匹配
        //     return nullptr; 
        assert(typeid(T) == _content->type()); // 断言类型匹配 --> 不匹配直接退出
        return &((placeholder<T>*)_content)->_val; // 类型转化->成员->取地址
    }  

    template<class T>
    Any& operator=(const T&val){  // 模板赋值运算符的重载
        // 先构造一个临时对象，然后交换
        Any(val).swap(*this); 
        return *this;
    }
    Any& operator=(const Any& other){
        Any(other).swap(*this);
        return *this;
    }
};

// 测试有无内存泄漏
struct Test{
    Test(){std::cout << "构造" << std::endl;}
    Test(const Test&other){std::cout << "拷贝构造" << std::endl;}
    ~Test(){std::cout << "析构" << std::endl;}
};

void func(){
    // 系统自带
    std::any a;
    a = 10;
    int *pi = std::any_cast<int>(&a);
    std::cout << "int a = " << *pi << std::endl; 

    a = std::string("hello");
    std::string *ps = std::any_cast<std::string>(&a);
    std::cout << "string a = " << *ps << std::endl;
}

int main()
{
    Any a;
    a = 10;
    int *pa = a.get<int>(); // 获取int类型的指针
    std::cout << "int a = " << *pa << std::endl; 

    a = std::string("hello");
    std::string *ps = a.get<std::string>();
    std::cout << "string a = " << *ps << std::endl; 

    // 两次析构对象: 相当于在 placeholder 中保存了一个对象的引用
    // 先析构原来的对象，再析构临时对象
    {
        Test t;
        a = t;
    }

    std::cout << "------------" << std::endl;
    func(); // 测试系统自带的any类

    return 0;
}